﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;

namespace Tzw.Common
{
    public static class DataSetExtend
    {

        #region DataTable转换成实体类

        /// <summary>
        /// 填充对象列表：用DataSet的第一个表填充实体类
        /// </summary>
        /// <param name="ds">DataSet</param>
        /// <returns></returns>
        public static List<T> FillModel<T>(this DataSet ds) where T : new()
        {
            if (ds?.Tables[0] == null || ds.Tables[0].Rows.Count == 0)
            {
                return null;
            }

            return ds.Tables[0].FillModel<T>();
        }

        /// <summary>  
        /// 填充对象列表：用DataSet的第index个表填充实体类
        /// </summary>  
        public static List<T> FillModel<T>(this DataSet ds, int index) where T : new()
        {
            if (ds == null || ds.Tables.Count <= index || ds.Tables[index].Rows.Count == 0)
            {
                return null;
            }

            return ds.Tables[index].FillModel<T>();
        }

        /// <summary>  
        /// 填充对象列表：用DataTable填充实体类　　　　
        /// </summary>  
        public static List<T> FillModel<T>(this DataTable dt) where T : new()
        {
            if (dt == null || dt.Rows.Count == 0)
            {
                return null;
            }

            List<T> modelList = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                modelList.Add(dr.FillModel<T>());
            }

            return modelList;
        }

        /// <summary>  
        /// 填充对象：用DataRow填充实体类
        /// </summary>  
        public static T FillModel<T>(this DataRow dr) where T : new()
        {
            if (dr == null)
            {
                return default(T);
            }

            T model = new T();

            for (int i = 0; i < dr.Table.Columns.Count; i++)
            {
                PropertyInfo propertyInfo = model.GetType().GetProperty(dr.Table.Columns[i].ColumnName);
                if (propertyInfo != null && dr[i] != DBNull.Value)
                {
                    Type @typeof = propertyInfo.PropertyType; //这里是获取实体类字段属性
                    propertyInfo.SetValue(model, Convert.ChangeType(dr[i], @typeof),
                        null); //然后用 changetype方法进行转换，因为dr[i]获取到的都是string类型，需要进行转换
                }
            }

            return model;
        }

        #endregion

        #region 实体类转换成DataTable

        /// <summary>
        /// 实体类转换成DataSet
        /// </summary>
        /// <param name="modelList">实体类列表</param>
        /// <returns></returns>
        public static DataSet FillDataSet<T>(this List<T> modelList)
        {
            if (modelList == null || modelList.Count == 0)
            {
                return null;
            }

            DataSet ds = new DataSet();
            ds.Tables.Add(modelList.FillDataTable());
            return ds;
        }

        /// <summary>
        /// 实体类转换成DataTable
        /// </summary>
        /// <param name="modelList">实体类列表</param>
        /// <returns></returns>
        public static DataTable FillDataTable<T>(this List<T> modelList)
        {
            if (modelList == null || modelList.Count == 0)
            {
                return null;
            }

            DataTable dt = CreateData(modelList[0]);

            foreach (T model in modelList)
            {
                DataRow dataRow = dt.NewRow();
                foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
                {
                    dataRow[propertyInfo.Name] = propertyInfo.GetValue(model, null);
                }

                dt.Rows.Add(dataRow);
            }

            return dt;
        }

        /// <summary>
        /// 根据实体类得到表结构
        /// </summary>
        /// <param name="model">实体类</param>
        /// <returns></returns>
        private static DataTable CreateData<T>(T model)
        {
            DataTable dataTable = new DataTable(typeof(T).Name);
            foreach (PropertyInfo propertyInfo in typeof(T).GetProperties())
            {
                dataTable.Columns.Add(new DataColumn(propertyInfo.Name, propertyInfo.PropertyType));
            }

            return dataTable;
        }

        #endregion
    }

}